package vsy.buzzwordbingo.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import vsy.buzzwordbingo.model.Game;
import vsy.buzzwordbingo.model.GameBoard;
import vsy.buzzwordbingo.model.GameCore;
import vsy.buzzwordbingo.model.Player;
import vsy.buzzwordbingo.util.ControllerUtil;

@Controller
public class JSONController {

	@Resource
	private GameCore gameCore;
	
	@RequestMapping(value = "/json/games", method = RequestMethod.GET)
	public @ResponseBody List<Game> getGames(HttpServletRequest request,
			HttpServletResponse response) {
		response.setContentType("application/json");
		String playerName = request.getParameter("player"); 
		if (playerName == null)
			return gameCore.getGames();
		return gameCore.getPlayer(playerName).getGames(); 
	}
	
	@RequestMapping(value = "/json/games/{gameId}", method = RequestMethod.GET)
	public @ResponseBody Game getGame(HttpServletRequest request,
			HttpServletResponse response, @PathVariable String gameId) {
		response.setContentType("application/json");
		return gameCore.getGame(gameId);
	}
		
	@RequestMapping(value = "/json/players", method = RequestMethod.GET)
	public @ResponseBody List<Player> getPlayers(HttpServletRequest request,
			HttpServletResponse response) {
		response.setContentType("application/json");
		String gameId = request.getParameter("game");
		if (gameId == null)
			return gameCore.getPlayers();
		String playerName = request.getUserPrincipal().getName();
		gameCore.poll(gameId, playerName);
		return gameCore.getGame(gameId).getPlayers();
	}
	
	@RequestMapping(value = "/json/players/{name}", method = RequestMethod.GET)
	public @ResponseBody Player getPlayer(HttpServletRequest request,
			HttpServletResponse response, @PathVariable String name) {
		response.setContentType("application/json");
		return gameCore.getPlayer(name);
	}	
	
	@RequestMapping(value = "/json/boards", method = RequestMethod.GET)
	public @ResponseBody List<GameBoard> getBoardsByGame(HttpServletRequest request,
			HttpServletResponse response) {
		response.setContentType("application/json");
		String playerName = request.getParameter("player");
		String gameId = request.getParameter("game");
		if (playerName != null && gameId != null) {
			List<GameBoard> boards = new ArrayList<GameBoard>(1);
			boards.add(gameCore.getBoard(gameId, playerName));
			return boards;
		}
		if (playerName != null)
			return gameCore.getPlayer(playerName).getBoards();
		if (gameId != null)
			return gameCore.getGame(gameId).getBoards();
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/json/boards/", method = RequestMethod.POST)
	public ModelAndView changeBoard(HttpServletRequest request,
			HttpServletResponse response, @RequestParam String game, @RequestParam String player) {
		ObjectMapper mapper = new ObjectMapper();
		try {
			//Yes, this sucks. Dunno why the post data is added as a fucking parameter name
			//and I'm too lazy to find out. 
			String data = null;
			Enumeration parameterNames = request.getParameterNames();
			while (parameterNames.hasMoreElements()) {
				String parameterName = (String)parameterNames.nextElement();
				if (!"player".equals(parameterName) && !"game".equals(parameterName)) {
					data = parameterName;
					break;
				}
			}

			if (data != null) {
				List<List<Boolean>> board = mapper.readValue(data, ArrayList.class);
				for (int row = 0; row < board.size(); row++) {
					List<Boolean> rowList = board.get(row);
					for (int col = 0; col < rowList.size(); col++) {
						Boolean marked = rowList.get(col);
						gameCore.markBuzzword(game, player, row, col, marked);
					}	
				}
			}
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return ControllerUtil.createEmptyResponse("application/json", HttpStatus.OK);
	}
}
